#ifndef FTCM_HSM_AP_H
#define FTCM_HSM_AP_H

#include <stddef.h>
#include "libsecurity.h"
#define MAX_HASH_SIZE (1*1024*1024)

typedef int32_t aead_encrypt_ctx_t;
typedef int32_t aead_decrypt_ctx_t;
typedef int32_t mac_compute_ctx_t;
typedef int32_t psa_hash_operation_t;

typedef int32_t psa_status_t;

typedef uint32_t psa_algorithm_t;

typedef uint32_t mbedtls_svc_key_id_t;
typedef uint32_t psa_key_attributes_t;

#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x00000000)
#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000000)
#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x02000000)
#define PSA_ALG_MSHA_HMAC1 ((psa_algorithm_t)0x03000000)
#define PSA_ALG_MSHA_HMAC224 ((psa_algorithm_t)0x04000000)
#define PSA_ALG_MSHA_HMAC256 ((psa_algorithm_t)0x05000000)
#define PSA_ALG_CMAC ((psa_algorithm_t)0x06000000)

#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW ((psa_algorithm_t)0x10000000)
#define PSA_ALG_RSA_PSS_SIGN_RAW ((psa_algorithm_t)0x11000000)
#define PSA_ALG_ECB_NO_PADDING ((psa_algorithm_t)0x04000000)
#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04000001)

#define PSA_OK ((psa_status_t)0)
#define PSA_SUCCESS ((psa_status_t)0)
#define PSA_ERROR ((psa_status_t)-132)

#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134)
#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133)
#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138)
#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135)
#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141)
#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142)
#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145)
#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146)
#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147)
#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149)
#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150)
#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148)
#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136)

typedef struct {
    psa_algorithm_t alg;
    union {
        struct {
            uint8_t *data;
            size_t length;
        } symmetric;
        
        struct {
            uint8_t *modulus;
            size_t modulus_length;
            uint8_t *public_exponent;
            size_t public_exponent_length;
            uint8_t *private_exponent;
            size_t private_exponent_length;
        } rsa;
    } key_data;
    uint8_t key_type;
} ftcm_key_hsm;

int ftcm_hsm_ap_import_key(uint32_t keyid, ftcm_key_hsm *key);
int ftcm_hsm_ap_export_pubkey_byid(uint32_t keyid, ftcm_key_hsm *key);

psa_status_t ftcm_hsm_ap_generate_random(uint8_t *output, size_t output_size);

psa_status_t ftcm_hsm_ap_hash_compute(psa_algorithm_t alg,
                                      const uint8_t *input,
                                      size_t input_length,
                                      uint8_t *hash,
                                      size_t hash_size,
                                      size_t *hash_length);

psa_status_t ftcm_hsm_ap_hash_setup(psa_hash_operation_t *operation,
                                    psa_algorithm_t alg);

psa_status_t ftcm_hsm_ap_hash_update(psa_hash_operation_t *operation,
                                     const uint8_t *input,
                                     size_t input_length);

psa_status_t ftcm_hsm_ap_hash_finish(psa_hash_operation_t *operation,
                                     uint8_t *hash,
                                     size_t hash_size,
                                     size_t *hash_length);

psa_status_t ftcm_hsm_ap_cipher_encrypt(mbedtls_svc_key_id_t key,
                                        psa_algorithm_t alg,
                                        const uint8_t *input,
                                        size_t input_length,
                                        uint8_t *output,
                                        size_t output_size,
                                        size_t *output_length);

psa_status_t ftcm_hsm_ap_cipher_decrypt(mbedtls_svc_key_id_t key,
                                        psa_algorithm_t alg,
                                        const uint8_t *input,
                                        size_t input_length,
                                        uint8_t *output,
                                        size_t output_size,
                                        size_t *output_length);

psa_status_t ftcm_hsm_ap_aead_encrypt(mbedtls_svc_key_id_t key,
                                      psa_algorithm_t alg,
                                      const uint8_t *nonce_external,
                                      size_t nonce_length,
                                      size_t tag_length,
                                      const uint8_t *additional_data_external,
                                      size_t additional_data_length,
                                      const uint8_t *plaintext_external,
                                      size_t plaintext_length,
                                      uint8_t *ciphertext_external,
                                      size_t ciphertext_size,
                                      size_t *ciphertext_length);

psa_status_t ftcm_hsm_ap_aead_decrypt(mbedtls_svc_key_id_t key,
                                      psa_algorithm_t alg,
                                      const uint8_t *nonce_external,
                                      size_t nonce_length,
                                      size_t tag_length,
                                      const uint8_t *additional_data_external,
                                      size_t additional_data_length,
                                      const uint8_t *ciphertext_external,
                                      size_t ciphertext_length,
                                      uint8_t *plaintext_external,
                                      size_t plaintext_size,
                                      size_t *plaintext_length);

psa_status_t ftcm_hsm_ap_aead_encrypt_setup(
    aead_encrypt_ctx_t *ctx,
    mbedtls_svc_key_id_t key,
    psa_algorithm_t alg,
    const uint8_t *nonce_external,
    size_t nonce_length,
    size_t tag_length,
    const uint8_t *additional_data,
    size_t ad_length);

psa_status_t ftcm_hsm_ap_aead_encrypt_update(
    aead_encrypt_ctx_t *ctx,
    const uint8_t *plaintext,
    size_t plaintext_length,
    uint8_t *ciphertext,
    size_t ciphertext_size,
    size_t *ciphertext_length);

psa_status_t ftcm_hsm_ap_aead_encrypt_finish(
    aead_encrypt_ctx_t *ctx,
    uint8_t *ciphertext,
    size_t ciphertext_size,
    size_t *ciphertext_length,
    uint8_t *tag,
    size_t tag_size);

psa_status_t ftcm_hsm_ap_aead_decrypt_setup(
    aead_decrypt_ctx_t *ctx,
    mbedtls_svc_key_id_t key,
    psa_algorithm_t alg,
    const uint8_t *nonce_external,
    size_t nonce_length,
    size_t tag_length,
    const uint8_t *additional_data,
    size_t ad_length);

psa_status_t ftcm_hsm_ap_aead_decrypt_update(
    aead_decrypt_ctx_t *ctx,
    const uint8_t *ciphertext,
    size_t ciphertext_length,
    uint8_t *plaintext,
    size_t plaintext_size,
    size_t *plaintext_length);

psa_status_t ftcm_hsm_ap_aead_decrypt_finish(
    aead_decrypt_ctx_t *ctx,
    const uint8_t *tag,
    size_t tag_length,
    uint8_t *plaintext,
    size_t plaintext_size,
    size_t *plaintext_length);

psa_status_t ftcm_hsm_ap_mac_compute(mbedtls_svc_key_id_t key,
                                     psa_algorithm_t alg,
                                     const uint8_t *input,
                                     size_t input_length,
                                     uint8_t *mac,
                                     size_t mac_size,
                                     size_t *mac_length);

psa_status_t ftcm_hsm_ap_mac_setup(
    mac_compute_ctx_t *ctx,
    mbedtls_svc_key_id_t key,
    psa_algorithm_t alg);

psa_status_t ftcm_hsm_ap_mac_update(
    mac_compute_ctx_t *ctx,
    const uint8_t *input,
    size_t input_length);

psa_status_t ftcm_hsm_ap_mac_finish(
    mac_compute_ctx_t *ctx,
    uint8_t *mac,
    size_t mac_size,
    size_t *mac_length);

psa_status_t ftcm_hsm_ap_rsa_generate_key(const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key);

psa_status_t ftcm_hsm_ap_rsa_encrypt(mbedtls_svc_key_id_t key,
                                     psa_algorithm_t alg,
                                     const uint8_t *input,
                                     size_t input_length,
                                     const uint8_t *salt,
                                     size_t salt_length,
                                     uint8_t *output,
                                     size_t output_size,
                                     size_t *output_length);

psa_status_t ftcm_hsm_ap_rsa_decrypt(mbedtls_svc_key_id_t key,
                                     psa_algorithm_t alg,
                                     const uint8_t *input,
                                     size_t input_length,
                                     const uint8_t *salt,
                                     size_t salt_length,
                                     uint8_t *output,
                                     size_t output_size,
                                     size_t *output_length);

psa_status_t ftcm_hsm_ap_rsa_sign(mbedtls_svc_key_id_t key,
                                  psa_algorithm_t alg,
                                  const uint8_t *input,
                                  size_t input_length,
                                  uint8_t *signature,
                                  size_t signature_size,
                                  size_t *signature_length);

psa_status_t ftcm_hsm_ap_rsa_verify(mbedtls_svc_key_id_t key,
                                    psa_algorithm_t alg,
                                    const uint8_t *input,
                                    size_t input_length,
                                    const uint8_t *signature,
                                    size_t signature_length);

#endif